#ifndef INVERTED_INDEX_H
#define INVERTED_INDEX_H

#include <string>
#include <map>
#include <unordered_map>
#include <vector>

class PostingList {
public:
    PostingList();
    PostingList(std::string token);
    ~PostingList();

    std::string GetToken();
    int GetOccur();
    int GetDocCount();
    int InsertPosing(int docID, int pos);
    int MergePosing(PostingList &postingList);
    // 生成的二进制序列使用后，需要主动delete []内存
    int Encode(unsigned char **buf, int &size);
    // 分析二进制数据，设置内部变量
    int Decode(unsigned char *buf, int size);

    using DocIterator = std::map<int, std::vector<int>>::iterator;
    DocIterator DocBegin()
    {
        return posting_.begin();
    }

    DocIterator DocEnd()
    {
        return posting_.end();
    }

    void DocNext(DocIterator &iteror)
    {
        ++iteror;
    }

    int GetDocID(DocIterator &iterator)
    {
        return iterator->first;
    }

    using PosIterator = std::vector<int>::iterator;
    PosIterator PosBegin(int docID)
    {
        return posting_[docID].begin();
    }

    PosIterator PosEnd(int docID)
    {
        return posting_[docID].end();
    }

    void PosNext(PosIterator &iteror)
    {
        ++iteror;
    }

    int GetPos(PosIterator &iterator)
    {
        return *iterator;
    }

private:
    int occur_;
    std::string token_;
    std::map<int, std::vector<int>> posting_; // <docID, [pos1, pos2,...]>
};

class InvertedIndex {
public:
    InvertedIndex();
    InvertedIndex(int threshold);
    ~InvertedIndex();

    using Iterator = std::unordered_map<std::string, PostingList>::iterator;

    bool IsFull()
    {
        return doc_count_ >= threshold_;
    }

    int AddPosting(std::string &token, int docID, int pos);
    int MergeIndex(InvertedIndex &index);
    int AddDoc(int count);

    Iterator Begin()
    {
        return index_.begin();
    }

    Iterator End()
    {
        return index_.end();
    }

    void Clear()
    {
        index_.clear();
        doc_count_ = 0;
    }

private:
    std::unordered_map<std::string, PostingList> index_;
    int doc_count_; /* 文档个数 */
    int threshold_; /* 文档最大个数 */
};


#endif
